﻿using Core.Info;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;

namespace Core.Utility.Helper
{

    /// <summary>
    /// 异常信息助手类
    /// </summary>
    public static class ExceptionMessageHelper
    {

        /// <summary>
        /// 获取异常详细信息，通常用于完整的异常信息输出
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="exHierarchy"></param>
        /// <returns></returns>
        public static string DetailInfo(this Exception ex, int exHierarchy = 0)
        {
            exHierarchy++;
            StringBuilder detailInfo = new StringBuilder();
            if (!string.IsNullOrEmpty(DetailMessage(ex)))
            {
                detailInfo.AppendLine($"Exception-Message:");
                detailInfo.AppendLine($"    {ex?.Message}");
            }

            if (ex?.TargetSite != null)
            {
                if (!string.IsNullOrEmpty(ex?.TargetSite?.DeclaringType?.FullName))
                {
                    detailInfo.AppendLine($"Exception-Method:");
                    detailInfo.AppendLine($"    {ex?.TargetSite.DeclaringType.FullName} {ex?.TargetSite.ToString()}");
                }
                detailInfo.AppendLine($"Exception-TargetSite:");
                detailInfo.AppendLine($"    {ex?.TargetSite}");
            }

            if (!string.IsNullOrEmpty(ex?.Source))
            {
                detailInfo.AppendLine($"Exception-Source:");
                detailInfo.AppendLine($"    {ex?.Source}");
            }

            if (!string.IsNullOrEmpty(ex?.StackTrace))
            {
                detailInfo.AppendLine($"Exception-StackTrace:");
                detailInfo.AppendLine($"    {ex?.StackTrace}");
            }

            if (!string.IsNullOrEmpty(ex?.HelpLink))
            {
                detailInfo.AppendLine($"Exception-HelpLink:");
                detailInfo.AppendLine($"    {ex?.HelpLink}");
            }

            if (ex?.InnerException != null)
            {
                string innerExceptionInfo = DetailInfo(ex.InnerException, exHierarchy);
                if (!string.IsNullOrEmpty(innerExceptionInfo))
                {
                    string strExHierarchy = exHierarchy.ToString().PadLeft(2, '0');
                    string strSplit = "".ToString().PadLeft(10 - exHierarchy, '-');
                    string strSpace = "".ToString().PadLeft(exHierarchy * 2, ' ');
                    detailInfo.AppendLine("");
                    detailInfo.AppendLine($"{strSpace}{strSplit} [{strExHierarchy}] ---------- [{strExHierarchy}] {strSplit}");
                    detailInfo.Append(innerExceptionInfo);
                    detailInfo.AppendLine($"{strSpace}{strSplit} [{strExHierarchy}] ---------- [{strExHierarchy}] {strSplit}");
                }
            }
            return detailInfo?.ToString() ?? "";

        }

        /// <summary>
        /// 通过递归获取异常信息的所有<see cref="Exception.Message"/>,通常用于友好信息展示
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="exHierarchy"></param>
        /// <returns></returns>
        public static string DetailMessage(this Exception ex, int exHierarchy = 0)
        {
            exHierarchy++;
            StringBuilder message = new StringBuilder();
            if (!string.IsNullOrEmpty(ex.Message.Trim()))
            {
                message.AppendLine($"{ex.Message.Trim()}" );
            }
            if (ex?.InnerException != null)
            {
                string innerExceptonMessage = DetailMessage(ex.InnerException, exHierarchy);
                if (!string.IsNullOrEmpty(innerExceptonMessage.Trim()))
                {
                    string strExHierarchy = exHierarchy.ToString().PadLeft(2, '0');
                    string strSplit = "".ToString().PadLeft(10 - exHierarchy, '-');
                    string strSpace = "".ToString().PadLeft(exHierarchy * 2, ' ');
                    message.AppendLine("");
                    message.AppendLine($"{strSpace}{strSplit} [{strExHierarchy}] ---------- [{strExHierarchy}] {strSplit}");
                    message.AppendLine(innerExceptonMessage.Trim());
                    message.AppendLine($"{strSpace}{strSplit} [{strExHierarchy}] ---------- [{strExHierarchy}] {strSplit}");
                }
            }
            return message.ToString();
        }

        /// <summary>
        /// 输出错误信息，根据 <see cref="RunTimeInfo.IsDebug"/> 与 <see cref="RunTimeInfo.IsDevelopment"/> 决定输出友好信息还是详细信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="topic">错误主题</param>
        /// <returns></returns>
        public static string Output(this Exception ex,string topic = "")
        {
            if(RunTimeInfo.IsDebug || RunTimeInfo.IsDevelopment)
            {
                return OutputMessage(ex,topic);
            }
            else
            {
                return OutputInfo(ex, topic);
            }
        }


        /// <summary>
        /// 输出错误信息，输出友好信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="topic">错误主题</param>
        /// <returns></returns>
        public static string OutputMessage(this Exception ex, string? topic = "")
        {
            StringBuilder sb = new StringBuilder();
            if (!string.IsNullOrEmpty(topic))
            {
                sb.AppendLine(topic);
            }
            sb.AppendLine(ex.DetailMessage());
            return sb.ToString();
        }


        /// <summary>
        /// 输出错误信息，输出详细信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="message"></param>
        /// <param name="topic"></param>
        /// <returns></returns>
        public static string OutputInfo(this Exception ex, string message = "",string? topic ="" )
        {
            StringBuilder sb = new StringBuilder();
            if (!string.IsNullOrEmpty(topic))
            {
                sb.AppendLine(topic);
            }
            if (!string.IsNullOrEmpty(message))
            {
                sb.AppendLine(message);
            }
            sb.AppendLine(ex.DetailInfo());
            return sb.ToString();
        }
    }
}
